package intcomp

import (
	"bytes"
	"errors"
)

type Uint24 uint32 //3个字节

type INT interface {
	int64 | int32 | int16 | int8 | uint64 | uint32 | uint16 | uint8 | Uint24
}

// const INVALID_VALUE = 0xffffffff   //无效数据
// const MASK_COUNT = 0x80000000      //数据掩码
// const MASK_COUNT_DATA = 0x7fffffff //数据个数

// 主要压缩连续的自增数据压缩，例如id列表
// 压缩的数据不能含有负数，且范围是有符号数的最大值，（压缩的最高位为数量位标志）
// 例如 uint16 能保存的最大数据是32766，超过这个数需要手动切换到 uint32类型
type SeqComp[N INT] struct {
	tmp           []byte
	buf           *bytes.Buffer
	lastValue     N //上一个数
	count         N
	autoIncre     bool            //是否是自增数据
	maskCount     N               // 1 << (i.length*8 - 1) = 0x80000000      //数据掩码
	maskCountData N               //^maskCount 0x7fffffff //数据个数
	length        int             //数据类型的长度
	encode        func([]byte, N) // 编码函数
	decode        func([]byte) N  //解码函数
}

// autoIncre true 是否是自增数据 false 压缩状态数据（大量相同值的数据）
func NewSeqComp[N INT](autoIncre bool) *SeqComp[N] {
	var t any = N(0)
	i := new(SeqComp[N])
	switch t.(type) {
	case int8, uint8:
		i.length = 1
		i.encode = i.PutUint8
		i.decode = i.Uint8
	case int16, uint16:
		i.length = 2
		i.encode = i.PutUint16
		i.decode = i.Uint16
	case Uint24:
		i.length = 3
		i.encode = i.PutUint24
		i.decode = i.Uint24
	case int32, uint32:
		i.length = 4
		i.encode = i.PutUint32
		i.decode = i.Uint32
	case int64, uint64:
		i.length = 8
		i.encode = i.PutUint64
		i.decode = i.Uint64
	default:
		panic("范型类型错误")
	}
	i.tmp = make([]byte, i.length*2)
	i.maskCount = 1 << (i.length*8 - 1)
	i.maskCountData = ^i.maskCount
	i.autoIncre = autoIncre
	return i
}

// 编码前必须调用此方法
func (m *SeqComp[N]) Reset() *SeqComp[N] {
	m.lastValue = 0
	m.count = 0
	if m.buf == nil {
		m.buf = bytes.NewBuffer(nil)
	} else {
		m.buf.Reset()
	}
	return m
}

func (m *SeqComp[N]) SetAutoIncre(b bool) {
	m.autoIncre = b
}

// 写入到缓存中
func (m *SeqComp[N]) Write(ival N) {
	if m.count >= m.maskCountData { //达到最大值
		m.Flush()
	}
	ival &= m.maskCountData //保证数据没有超过限制
	if m.autoIncre {
		if ival == (m.lastValue + 1) {
			m.count++
			m.lastValue = ival
			return
		}
	} else {
		if ival == m.lastValue {
			m.count++
			m.lastValue = ival
			return
		}
	}

	if m.count > 0 {
		m.Flush()
	}
	m.lastValue = ival
	m.count++
}

func (m *SeqComp[N]) Flush() {
	if m.buf == nil {
		m.buf = bytes.NewBuffer(nil)
	}
	switch m.count {
	case 0:
		return //没有数据不做任何处理
	case 1:
		//只有一个数据,直接保存
		m.encode(m.tmp, m.lastValue)
		m.buf.Write(m.tmp[:m.length])
		m.count = 0
	default:
		m.encode(m.tmp, m.count|m.maskCount)
		if m.autoIncre {
			m.encode(m.tmp[m.length:], m.lastValue-(m.count-1))
		} else {
			m.encode(m.tmp[m.length:], m.lastValue)
		}
		m.buf.Write(m.tmp[:m.length*2])
		m.count = 0
	}
}

func (m *SeqComp[N]) Bytes() []byte {
	m.Flush()
	return m.buf.Bytes()
}

func (m *SeqComp[N]) Encode(ivals []N) []byte {
	for _, ival := range ivals {
		m.Write(ival)
	}
	return m.Bytes()
}

func (m *SeqComp[N]) Decode(data []byte) (ids []N, err error) {
	//统计需要的空间
	l := len(data)
	if l%m.length != 0 {
		err = errors.New("数据格式错误")
		return
	}
	n := int(0)
	for i := 0; i < l; i += m.length {
		ival := m.decode(data[i:]) //binary.BigEndian.Uint32(data[i:])
		if ival&m.maskCount != 0 {
			n += int(ival & m.maskCountData)
			i += m.length //跳过开始值
		} else {
			n++
		}
	}
	ids = make([]N, n)
	idx := 0
	for i := 0; i < l; i += m.length {
		ival := m.decode(data[i:]) //binary.BigEndian.Uint32(data[i:])
		if ival&m.maskCount != 0 {
			n = int(ival & m.maskCountData)
			i += m.length               //跳过开始值
			begin := m.decode(data[i:]) //binary.BigEndian.Uint32(data[i:])
			if m.autoIncre {
				for j := 0; j < n; j++ {
					ids[idx] = begin + N(j)
					idx++
				}
			} else {
				for j := 0; j < n; j++ {
					ids[idx] = begin
					idx++
				}
			}
		} else {
			ids[idx] = ival
			idx++
		}
	}
	return
}

func (m *SeqComp[N]) Uint8(b []byte) N {
	return N(b[0])
}
func (m *SeqComp[N]) Uint16(b []byte) N {
	_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
	return N(uint16(b[1]) | uint16(b[0])<<8)
}
func (m *SeqComp[N]) Uint24(b []byte) N {
	_ = b[2] // bounds check hint to compiler; see golang.org/issue/14808
	return N(uint32(b[2]) | uint32(b[1])<<8 | uint32(b[0])<<16)
}

func (m *SeqComp[N]) Uint32(b []byte) N {
	_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
	return N(uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24)
}
func (m *SeqComp[N]) Uint64(b []byte) N {
	_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
	return N(uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
		uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56)
}

func (m *SeqComp[N]) PutUint8(b []byte, v N) {
	b[0] = byte(v)
}

func (m *SeqComp[N]) PutUint16(b []byte, vv N) {
	_ = b[1] // early bounds check to guarantee safety of writes below
	v := uint16(vv)
	b[0] = byte(v >> 8)
	b[1] = byte(v)
}

func (m *SeqComp[N]) PutUint24(b []byte, vv N) {
	_ = b[2] // early bounds check to guarantee safety of writes below
	v := uint32(vv)
	b[0] = byte(v >> 16)
	b[1] = byte(v >> 8)
	b[2] = byte(v)
}

func (m *SeqComp[N]) PutUint32(b []byte, vv N) {
	_ = b[3] // early bounds check to guarantee safety of writes below
	v := uint32(vv)
	b[0] = byte(v >> 24)
	b[1] = byte(v >> 16)
	b[2] = byte(v >> 8)
	b[3] = byte(v)
}

func (m *SeqComp[N]) PutUint64(b []byte, vv N) {
	_ = b[7] // early bounds check to guarantee safety of writes below
	v := uint64(vv)
	b[0] = byte(v >> 56)
	b[1] = byte(v >> 48)
	b[2] = byte(v >> 40)
	b[3] = byte(v >> 32)
	b[4] = byte(v >> 24)
	b[5] = byte(v >> 16)
	b[6] = byte(v >> 8)
	b[7] = byte(v)
}
